package com.bflow.impl;

import com.bflow.api.*;
import com.bflow.api.bo.*;
import com.bflow.api.bo.draw.DrawBo;
import com.bflow.api.bo.ext.BflowUserBo;
import com.bflow.api.constant.BflowConstant;
import com.bflow.commons.consts.CommConst;
import com.bflow.commons.exception.BizException;
import com.bflow.commons.service.BaseService;
import com.bflow.dao.BflowDefineProcessDrawDao;
import com.bflow.dao.po.BflowDefineProcessDrawPo;
import com.bflow.util.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.bflow.api.bo.draw.DrawBo;
import java.util.List;
import java.util.ArrayList;
import java.io.Serializable;

/**
 * @Name BflowDefineProcessDraw 流程定义图画-实现业务接口
 * @Author haowen
 * @Date 2019-01-10
 */
@Service("bflowDefineProcessDrawService")
public class BflowDefineProcessDrawServiceImpl extends BaseService<BflowDefineProcessDrawPo, BflowDefineProcessDrawBo> implements IBflowDefineProcessDrawService<BflowDefineProcessDrawPo, BflowDefineProcessDrawBo> {

	private static final Logger logger = LoggerFactory.getLogger(BflowDefineProcessDrawServiceImpl.class);

	@Autowired
	private BflowDefineProcessDrawDao dao;

	@Autowired
	private IBflowRunTaskService<?, BflowRunTaskBo> bflowRunTaskService;

	@Autowired
	private IBflowDefineProcessService<?, BflowDefineProcessBo> bflowDefineProcessService;
	
	@Autowired
	private IBflowDefineActService<?, BflowDefineActBo> bflowDefineActService;
	@Autowired
	private IBflowDefineActRouteService<?, BflowDefineActRouteBo> bflowDefineActRouteService;
	@Autowired
	private IBflowRunRecordService<?,BflowRunRecordBo> bflowRunRecordService;


	@Autowired
	private IBflowRunInstanceService<?, BflowRunInstanceBo> bflowRunInstanceService;
	

	@Override
	protected BflowDefineProcessDrawDao getDao() {
		return dao;
	}

	private void validate(BflowDefineProcessDrawBo bo){
		AssertUtil.isNotNull(bo, "提交不能为空");
		AssertUtil.isNotNull(bo.getTitle(), "说明 不能为空");
		AssertUtil.isNotNull(bo.getDrawKey(), "图画KEY 不能为空");
	}

    @Transactional
	@Override
	public Long save(BflowDefineProcessDrawBo bo) {
		validate(bo); //校验
		Long id = SysSeqUtil.generateId();
		bo.setId(id);
		BflowDefineProcessDrawPo po = BeanMapper.map(bo, BflowDefineProcessDrawPo.class);
		if (dao.insert(po) <= 0) {
			throw new BizException("新增失败");
		}
		return id;
	}

	@Override
	public BflowDefineProcessDrawBo get(String procId, String drawKey) throws BizException {
		BflowDefineProcessDrawBo queryBo = new BflowDefineProcessDrawBo();
		queryBo.setProcId(procId);
		queryBo.setDrawKey(drawKey);
		queryBo.setDelFlag(CommConst.STATUS_Y);
		return getOneBy(queryBo);
	}


	@Override
	public DrawBo getDraw(String processId) throws BizException {
		AssertUtil.isNotNull(processId,"流程模型id不能为空");
		//先查询是否有保存过 如果保存过直接取json

		BflowDefineProcessBo process = bflowDefineProcessService.findById(processId);
		AssertUtil.isNotNull(process, "流程模型id无效");

		BflowDefineProcessDrawBo drawByKey = this.getDrawByKey(process.getKey());
		if(drawByKey!=null){
			String json = drawByKey.getJson();
			json=StringEscapeUtils.unescapeHtml4(json);
			json=json.replaceAll("\r\n","");
			DrawBo drawBo = JsonUtil.toJavaObj(json, DrawBo.class);
			drawBo.setDraw(drawByKey);
			return drawBo;
		}

		String[] actArray = process.getActArray();
		List<DrawBo.Node> nodes=new ArrayList<DrawBo.Node>();
		List<DrawBo.Line> lines=new ArrayList<DrawBo.Line>();
		BflowDefineActRouteBo routeQuery=null;
		for(int i=0;i<actArray.length;i++){
			BflowDefineActBo act = bflowDefineActService.findById(actArray[i]);
			DrawBo.Node node=new DrawBo().new Node(act.getKey(),act.getName(),null,act.getDesc());
			nodes.add(node);
			routeQuery=new BflowDefineActRouteBo();
			routeQuery.setProcId(processId);
			routeQuery.setActId(act.getId());
			routeQuery.setStatus(CommConst.STATUS_Y);
			List<BflowDefineActRouteBo> routes = bflowDefineActRouteService.getListBy(routeQuery);
			if(CollectionUtils.isNotEmpty(routes)){
				for(BflowDefineActRouteBo r:routes){
					BflowDefineActBo nextAct=bflowDefineActService.findById(r.getNextActId());
					if(nextAct!=null){
						DrawBo.Line line=new DrawBo().new Line(act.getKey(),nextAct.getKey(),r.getCondDesc(),null);
						lines.add(line);
					}
				}
			}
		}
		return new DrawBo(nodes,lines,null);
	}

	@Override
	public DrawBo getDrawByInstanceId(String instanceId, String userId) throws BizException {
		AssertUtil.isNotNull(instanceId,"流程实例id不能为空");
		//先查询是否有保存过 如果保存过直接取json
		BflowRunInstanceBo instance = bflowRunInstanceService.findById(instanceId);
		AssertUtil.isNotNull(instance,"流程实例id无效");
		BflowDefineProcessDrawBo drawByKey = this.getDrawByKey(instance.getProcKey());
		//如果数据库中已经配置过图表布局 则直接使用布局位置
		if(drawByKey==null){
			throw new BizException("流程画板未配置,请先配置流程画板");
		}
		String json = drawByKey.getJson();
		json=StringEscapeUtils.unescapeHtml4(json);
		json=json.replaceAll("\r\n","");
		DrawBo drawBo = JsonUtil.toJavaObj(json, DrawBo.class);
		List<DrawBo.Node> nodeDataArray = drawBo.getNodeDataArray();


		BflowDefineProcessBo flowModelBykey = bflowDefineProcessService.getFlowModelBykey(instance.getProcKey());
		String procId=flowModelBykey.getId();
		BflowRunTaskBo runQuery=new BflowRunTaskBo();
		runQuery.setProcId(procId);
		runQuery.setInstanceId(instance.getId());
		runQuery.setStatus(BflowConstant.RunTaskStatus.WAITING_DEAL.getCode());
		BflowRunTaskBo waitTask = bflowRunTaskService.getOneBy(runQuery);
		String  waitActKey="";
		if(waitTask!=null){
		BflowDefineActBo waitAct = bflowDefineActService.findById(waitTask.getActId());
			waitActKey=waitAct.getKey();
		}
		for(DrawBo.Node n:nodeDataArray){
			this.processNode(n,instance,waitActKey);
		}
		List<DrawBo.Line> linkDataArray = drawBo.getLinkDataArray();
		for(DrawBo.Line l:linkDataArray){
			this.processLine(l,instance,waitActKey);
		}
		drawBo.setDraw(drawByKey);
		return drawBo;
//
//		//数据库没有设置过 则重新查询数据组装
//		BflowDefineProcessBo process = bflowDefineProcessService.getFlowModelBykey(instance.getProcKey());
//		AssertUtil.isNotNull(process, "流程模型id无效");
//		String[] actArray = process.getActArray();
//		List<DrawBo.Node> nodes=new ArrayList<DrawBo.Node>();
//		List<DrawBo.Line> lines=new ArrayList<DrawBo.Line>();
//		BflowDefineActRouteBo routeQuery=null;
//
//		for(int i=0;i<actArray.length;i++){
//			BflowDefineActBo act = bflowDefineActService.findById(actArray[i]);
//			DrawBo.Node node=new DrawBo().new Node(act.getKey(),act.getName(),null,act.getDesc());
//			nodes.add(node);
//			routeQuery=new BflowDefineActRouteBo();
//			routeQuery.setProcId(process.getId());
//			routeQuery.setActId(act.getId());
//			List<BflowDefineActRouteBo> routes = bflowDefineActRouteService.getListBy(routeQuery);
//			if(CollectionUtils.isNotEmpty(routes)){
//				for(BflowDefineActRouteBo r:routes){
//					BflowDefineActBo nextAct=bflowDefineActService.findById(r.getNextActId());
//					if(nextAct!=null){
//						BflowRunRecordBo handle = this.isHandle(act.getId(), instanceId);
//						if(handle!=null){
//							DrawBo.Line line=new DrawBo().new Line(act.getKey(),nextAct.getKey(),handle.getFlag()+"("+DateUtils.formatDateTime(handle.getCreateTime())+")"+" 处理人:"+handle.getCreateUname(),"lightgreen");
//							lines.add(line);
//							continue;
//						}
//						DrawBo.Line line=new DrawBo().new Line(act.getKey(),nextAct.getKey(),r.getCondDesc(),null);
//						lines.add(line);
//					}
//				}
//			}
//		}
//		return new DrawBo(nodes,lines,null);
	}


	/**
	 * 处理节点信息
	 * @param node
	 * @return
	 */
	private DrawBo.Node processNode(DrawBo.Node node,BflowRunInstanceBo instance,String waitActKey){

		if(node.getId().equals(DrawBo.NODE_START)){


		}else if(node.getId().equals(DrawBo.NODE_END)){


		}else {
			BflowDefineActBo act = bflowDefineActService.getCacheByKey(node.getId());
			BflowRunRecordBo handle = this.isHandle(act.getId(), instance.getId());
			if(handle!=null){
				node.setColor("lightgreen");
			}else{
				if(node.getId().equals(waitActKey)){
					node.setText(node.getText()+"(待审批)");
				}
			}
		}
		return  node;
	};

	/**
	 * 处理线条信息
	 * @param line
	 * @return
	 */
	private DrawBo.Line processLine(DrawBo.Line line,BflowRunInstanceBo instance,String waitActKey){
		//标记用于是否修改组装的颜色 提示等
		Boolean isUpdate=false;
		//开始节点线
		if(line.getFrom().equals(DrawBo.NODE_START)){
			line.setText("提交申请("+ DateUtils.formatDateTime(instance.getCreateTime())+")\n"+instance.getStartUname());
		//判断最后一条线条 如果已经处理过则修改数据
		}else if(line.getTo().equals(DrawBo.NODE_END) && line.getFrom().equals(waitActKey)){
			isUpdate=true;
		}else{
			isUpdate=true;
		}

		if(isUpdate){
			BflowDefineActBo act = bflowDefineActService.getCacheByKey(line.getFrom());
			BflowRunRecordBo handle = this.isHandle(act.getId(), instance.getId());
			if(handle!=null){
				BflowRunTaskBo task = bflowRunTaskService.findById(handle.getTaskId());
				line.setLineColor("lightgreen");
				BflowUserBo bflowUserBo = BflowExtResServiceImpl.USER_LIST.get(task.getUserKey());
				if(bflowUserBo!=null){
					line.setText(handle.getFlag()+"("+DateUtils.formatDateTime(handle.getCreateTime())+")"+"\n 处理人:"+bflowUserBo.getUserName());
				}
			}
		}
		return  line;
	};


	/**
	 * 查询处理信息 如果存在记录则线条已经处理通过
	 * @param actId
	 * @param instanceId
	 * @return
	 */
	private BflowRunRecordBo isHandle(String actId,String instanceId){
		BflowRunRecordBo query=new BflowRunRecordBo();
		query.setCurActId(actId);
		query.setInstanceId(instanceId);
		query.setDelFlag(BflowConstant.CommStatus.Y.getCode());
		return bflowRunRecordService.getOneBy(query);
	}

	@Override
	public BflowDefineProcessDrawBo getDrawByKey(String key) throws BizException {
		BflowDefineProcessDrawBo query=new BflowDefineProcessDrawBo();
		query.setDelFlag(CommConst.STATUS_Y);
		query.setDrawKey(key);
		return this.getOneBy(query);
	};


}
